﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using DimsMapper.Modules;

namespace DimsMapper
{
    public class Map
    {
        // Raw map data
        Int32 version;                   // 0x0000
        Byte[] mapName = new Byte[16];   // 0x0004
        Int32 defPlayerPosition;         // 0x0014 :: Default player position [0..39999]
        Int32 defPlayerElevation;        // 0x0018 :: Default map elevation [0..2]
        Int32 defPlayerDirection;        // 0x001C :: Defuult player direction [0..5]
        Int32 localVars;                 // 0x0020 :: #Map Local Vars
        Int32 mapScriptID;               // 0x0024
        Int32 flags;                     // 0x0028
        Int32 darkness;                  // 0x002C :: According to BIS Mapper
        Int32 globalVars;                // 0x0030 :: #Map Global Vars (*.gam)
        Int32 mapID;                     // 0x0034
        Int32 gameLastVisitedTime;       // 0x0038 :: Time since the epoch.
        Byte[] unknown = new Byte[44*4]; // 0x003C -> 0x00EB

        //////////////////////////////////////////////////////

        string name; // внутреннее имя карты (обычно сопостовимо с именем файла)

        Int32[] globalVarsData;
        Int32[] localVarsData;

        int levels;
        int tilesSizeX, tilesSizeY;
        int tilesSize;

        TilesSet tiles;
        ScriptsSet scripts;
        ObjectsSet objects;

        public Map(DBFile file)
        {
            version = file.ReadInt();
            mapName = file.ReadBytes(16);
            defPlayerPosition = file.ReadInt();
            defPlayerElevation = file.ReadInt();
            defPlayerDirection = file.ReadInt();
            localVars = file.ReadInt();
            mapScriptID = file.ReadInt();
            flags = file.ReadInt();
            darkness = file.ReadInt();
            globalVars = file.ReadInt();
            mapID = file.ReadInt();
            gameLastVisitedTime = file.ReadInt();
            unknown = file.ReadBytes(44 * 4);

            if (globalVars > 0) {
                globalVarsData = new Int32[globalVars];
                for (int i = 0; i < globalVars; i++)
                {
                    globalVarsData[i] = file.ReadInt();
                }
            }

            if (localVars > 0) {
                localVarsData = new Int32[localVars];
                for (int i = 0; i < localVars; i++)
                {
                    localVarsData[i] = file.ReadInt();
                }
            }

            if ((flags & 2) == 0) levels++;
            if ((flags & 4) == 0) levels++;
            if ((flags & 8) == 0) levels++;

            switch (levels)
            {
                case 1:
                    tilesSizeX = 100;
                    tilesSizeY = 100;
                    break;
                case 2:
                    tilesSizeX = 100;
                    tilesSizeY = 200;
                    break;
                case 3:
                    tilesSizeX = 100;
                    tilesSizeY = 300;
                    break;
                default:
                    return; // ошибка
            }
            tilesSize = tilesSizeX * tilesSizeY;

            tiles = new TilesSet(file, tilesSize);
            scripts = new ScriptsSet(file);
            objects = new ObjectsSet(file);
        }

        public void Save(FileStream file)
        {

        }

        public string MapName
        {
            get {
                if (name == null) {
                    int len;
                    for (len = 0; len < 16; len++) {
                        if (mapName[len] == 0) break;
                    }
                    name = Encoding.ASCII.GetString(mapName, 0, len);
                } 
                return name;
            }
            set {
                if (value.Length >= 16) return;
                name = value;
                Encoding.ASCII.GetBytes(name).CopyTo(mapName, 0);
                for (int i = name.Length; i < 16; i++) {
                    mapName[i] = 0;
                }
            }
        }

        public int MapVersion
        {
            get { return version; }
        }

        public int Levels
        {
            get { return levels; }
        }

        public int PlayerStartTile
        {
            get { return (defPlayerPosition != -1) ? defPlayerPosition : 20100; }
        }

        internal TilesSet Tiles
        {
           get { return tiles; }
        }

        internal ScriptsSet Scripts
        {
            get { return scripts; }
        }

        internal ObjectsSet Objects
        {
            get { return objects; }
        }

        public int TilesCount
        {
            get { return tilesSize; }
        }

        public int TilesSizeX
        {
            get { return tilesSizeX; }
        }

        public int TilesSizeY
        {
            get { return tilesSizeY; }
        }
    }
}
